#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QDebug>
#include <QTime>
#include <QMessageBox>
#include <QFileDialog>

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);


    mySerialPort = new QSerialPort(this);

    ui->textBrowser->setStyleSheet("background-color:rgb(150,150,150);");
    ui->plainTextEdit->setStyleSheet("background-color:rgb(150,150,150);");

    ui->pushButton_4->setStyleSheet("background-color:rgb(0,255,0);");
    ui->pushButton_4->setText(tr("打开串口"));

    ui->comboBox_2->setCurrentText("9600");
    ui->comboBox_3->setCurrentText("NONE");
    ui->comboBox_4->setCurrentText("8");
    ui->comboBox_5->setCurrentText("1");

    ui->radioButton->setChecked(true);
    ui->radioButton_2->setChecked(false);
    ui->radioButton_5->setChecked(true);
    ui->radioButton_6->setChecked(false);

    ui->checkBox_3->setChecked(true);
    ui->checkBox_4->setChecked(true);

    hide = true;
    ui->pushButton_5->setText("<<");

    ui->groupBox_10->setStyleSheet("#groupBox_10{border:none}");

    sendNum = 0;
    recvNum = 0;
    // 状态栏
    QStatusBar *sBar = statusBar();
    // 状态栏的收、发计数标签
    lblSendNum = new QLabel(this);
    lblRecvNum = new QLabel(this);

    setNumOnLabel(lblSendNum, "S: ", sendNum);
    setNumOnLabel(lblRecvNum, "R: ", recvNum);
    // 从右往左依次添加
    sBar->addPermanentWidget(lblSendNum);
    sBar->addPermanentWidget(lblRecvNum);

    QStringList serialPortName;
    // 自动扫描当前可用串口，返回值追加到字符数组中
    foreach(const QSerialPortInfo &info, QSerialPortInfo::availablePorts()){
        serialPortName << info.portName();

        //将读取到的串口显示到界面上
        if (ui->comboBox->currentText() != info.portName())
            ui->comboBox->addItem(info.portName());
    }
    connect(mySerialPort, SIGNAL(readyRead()), this, SLOT(serialPortRead_Slot()));
}

MainWindow::~MainWindow()
{
    delete ui;
}
/*****************************************************************************************/
/*发送按钮*/
void MainWindow::on_pushButton_clicked()
{

    QByteArray sendData;

    if(ui->checkBox_3->isChecked()){
        ui->textBrowser->insertPlainText("\r\n");
        ui->textBrowser->setTextColor(QColor(255, 0, 0));
        QDateTime current_date_time =QDateTime::currentDateTime();
        QString current_date =current_date_time.toString("yyyy.MM.dd hh:mm:ss.zzz ddd");
        if(ui->radioButton_5->isChecked() == true){
            current_date = current_date + " <SEND ASCII>\r\n";
        }else{
            current_date = current_date + " <SEND HEX>\r\n";
        }
        qDebug()<<current_date;
        ui->textBrowser->insertPlainText(current_date);
    }

    // 判断是否为16进制发送，将发送区全部的asc2转换为16进制字符串显示，发送的时候转换为16进制发送
    if(ui->radioButton_5->isChecked() == true){
        // 字符串形式发送
        sendData = ui->plainTextEdit->toPlainText().toLocal8Bit().data();
    }else{
        // 16进制发送
        sendData = QByteArray::fromHex(ui->plainTextEdit->toPlainText().toUtf8()).data();
    }
    ui->textBrowser->setTextColor(QColor(0, 0, 0));
    ui->textBrowser->insertPlainText(sendData);
    int a = (int)mySerialPort->write(sendData);
    // 如发送成功，会返回发送的字节长度。失败，返回-1。
    // 发送字节计数并显示
    if(a > 0)
    {
        // 发送字节计数
        sendNum += a;
        // 状态栏显示计数值
        setNumOnLabel(lblSendNum, "S: ", sendNum);
    }
    ui->textBrowser->moveCursor(QTextCursor::End);


    if(ui->checkBox_4->isChecked()) {
        ui->textBrowser->insertPlainText("\r\n");
    }

    if(ui->checkBox->isChecked())
    {
        //将文本框数据取出并按行排列
        QFile file(textFile);//文件命名
        if (!file.open(QFile::WriteOnly | QFile::Text))     //检测文件是否打开
        {
            QMessageBox::information(this, "Error Message", "Please Select a Text File!");
            return;
        }
        QTextStream out(&file);                 //分行写入文件
        out << ui->textBrowser->toPlainText();
    }
}
/*清除发送区*/
void MainWindow::on_pushButton_2_clicked()
{
    qDebug() << "clean tx buff zone"<< endl;
    ui->plainTextEdit->clear();
}
/*清除接收区*/
void MainWindow::on_pushButton_3_clicked()
{
    qDebug() << "clean rx buff zone"<< endl;
    ui->textBrowser->clear();
}
/*打开关闭按钮*/
void MainWindow::on_pushButton_4_clicked()
{
    QSerialPort::BaudRate baudRate;
    QSerialPort::DataBits dataBits;
    QSerialPort::StopBits stopBits;
    QSerialPort::Parity   checkBits;
    if(ui->comboBox_2->currentText() == "1200"){
        baudRate = QSerialPort::Baud1200;
    }else if(ui->comboBox_2->currentText() == "2400"){
        baudRate = QSerialPort::Baud2400;
    }else if(ui->comboBox_2->currentText() == "4800"){
        baudRate = QSerialPort::Baud4800;
    }else if(ui->comboBox_2->currentText() == "9600"){
        baudRate = QSerialPort::Baud9600;
    }else if(ui->comboBox_2->currentText() == "19200"){
        baudRate = QSerialPort::Baud19200;
    }else if(ui->comboBox_2->currentText() == "38400"){
        baudRate = QSerialPort::Baud38400;
    }else if(ui->comboBox_2->currentText() == "57600"){
        baudRate = QSerialPort::Baud57600;
    }else if(ui->comboBox_2->currentText() == "115200"){
        baudRate = QSerialPort::Baud115200;
    }else{
        baudRate = QSerialPort::Baud9600;
    }

    // 获取串口奇偶校验位
    if(ui->comboBox_3->currentText() == "NONE"){
        checkBits = QSerialPort::NoParity;
    }else if(ui->comboBox_3->currentText() == "ODD"){
        checkBits = QSerialPort::OddParity;
    }else if(ui->comboBox_3->currentText() == "EVEN"){
        checkBits = QSerialPort::EvenParity;
    }else if(ui->comboBox_3->currentText() == "SPACE"){
        checkBits = QSerialPort::SpaceParity;
    }else if(ui->comboBox_3->currentText() == "MARK"){
        checkBits = QSerialPort::MarkParity;
    }else{
        checkBits = QSerialPort::UnknownParity;
    }

    // 获取串口数据位
    if(ui->comboBox_4->currentText() == "5"){
        dataBits = QSerialPort::Data5;
    }else if(ui->comboBox_4->currentText() == "6"){
        dataBits = QSerialPort::Data6;
    }else if(ui->comboBox_4->currentText() == "7"){
        dataBits = QSerialPort::Data7;
    }else if(ui->comboBox_4->currentText() == "8"){
        dataBits = QSerialPort::Data8;
    }else{

    }

    // 获取串口停止位
    if(ui->comboBox_5->currentText() == "1"){
        stopBits = QSerialPort::OneStop;
    }else if(ui->comboBox_5->currentText() == "1.5"){
        stopBits = QSerialPort::OneAndHalfStop;
    }else if(ui->comboBox_5->currentText() == "2"){
        stopBits = QSerialPort::TwoStop;
    }else{

    }

    // 想想用 substr strchr怎么从带有信息的字符串中提前串口号字符串
    // 初始化串口属性，设置 端口号、波特率、数据位、停止位、奇偶校验位数
    mySerialPort->setBaudRate(baudRate);
    mySerialPort->setDataBits(dataBits);
    mySerialPort->setParity(checkBits);
    mySerialPort->setStopBits(stopBits);

    QString spTxt = ui->comboBox->currentText();
    spTxt = spTxt.section(':', 0, 0);
    mySerialPort->setPortName(spTxt);

    if(ui->pushButton_4->text() == tr("打开串口")) {
        qDebug() << "open serial"<< endl;
        if(mySerialPort->open(QIODevice::ReadWrite) == true){
            ui->pushButton_4->setStyleSheet("background-color:rgb(255,0,0);");
            ui->pushButton_4->setText(tr("关闭串口"));
            ui->comboBox->setEnabled(false);
            ui->comboBox_2->setEnabled(false);
            ui->comboBox_3->setEnabled(false);
            ui->comboBox_4->setEnabled(false);
            ui->comboBox_5->setEnabled(false);
        }else{
            qDebug() << "open failed"<< endl;
        }
    }else {
        qDebug() << "close serial"<< endl;
        mySerialPort->close();
        ui->pushButton_4->setStyleSheet("background-color:rgb(0,255,0);");
        ui->pushButton_4->setText(tr("打开串口"));
        ui->comboBox->setEnabled(true);
        ui->comboBox_2->setEnabled(true);
        ui->comboBox_3->setEnabled(true);
        ui->comboBox_4->setEnabled(true);
        ui->comboBox_5->setEnabled(true);
    }
}
/*隐藏左部分设置区*/
void MainWindow::on_pushButton_5_clicked()
{
    if(hide == true)
    {
        setMinimumSize(800, 600);
        setMaximumSize(800, 600);
        ui->groupBox_4->hide();
        ui->groupBox_10->setGeometry(0,10,20,600);
        ui->groupBox_5->setGeometry(20,10,800,600);
        hide = false;
        ui->pushButton_5->setText(">>");

    }else {
        setFixedSize(1000,600);
        setMinimumSize(220, 600);
        setMaximumSize(1000, 600);
        ui->groupBox_4->show();
        ui->groupBox_10->setGeometry(200,10,20,600);
        ui->groupBox_5->setGeometry(220,10,800,600);
        hide = true;
        ui->pushButton_5->setText("<<");
    }
}

void MainWindow::on_pushButton_8_clicked()
{
    // 清除发送、接收字节计数
    sendNum = 0;
    recvNum = 0;
    // 状态栏显示计数值
    setNumOnLabel(lblSendNum, "S: ", sendNum);
    setNumOnLabel(lblRecvNum, "R: ", recvNum);
}
/*****************************************************************************************/
// 串口接收显示，槽函数
void MainWindow::serialPortRead_Slot()
{
    /*QString recBuf;
    recBuf = QString(mySerialPort->readAll());*/

    QByteArray recBuf;
    recBuf = mySerialPort->readAll();

    // 接收字节计数
    recvNum += recBuf.size();
    // 状态栏显示计数值
    setNumOnLabel(lblRecvNum, "R: ", recvNum);

    if(ui->checkBox_3->isChecked()){
        ui->textBrowser->insertPlainText("\r\n");
        ui->textBrowser->setTextColor(QColor(255, 0, 0));
        QDateTime current_date_time =QDateTime::currentDateTime();
        QString current_date =current_date_time.toString("yyyy.MM.dd hh:mm:ss.zzz ddd");
        if(ui->radioButton->isChecked() == true){
            current_date = current_date + " <RECV ASCII>\r\n";
        }else{
            current_date = current_date + " <RECV HEX>\r\n";
        }
        ui->textBrowser->insertPlainText(current_date);
    }

    ui->textBrowser->setTextColor(QColor(0, 0, 255));
    if(ui->radioButton->isChecked() == true)
    {
        ui->textBrowser->insertPlainText(recBuf);
    }else{
        QString str1 = recBuf.toHex().toUpper();//.data();
        // 添加空格
        QString str2;
        for(int i = 0; i<str1.length (); i+=2)
        {
            str2 += str1.mid (i,2);
            str2 += " ";
        }
        ui->textBrowser->insertPlainText(str2);
    }
    // 移动光标到文本结尾
    ui->textBrowser->moveCursor(QTextCursor::End);

    if(ui->checkBox_4->isChecked()) {
        ui->textBrowser->insertPlainText("\r\n");
    }

    if(ui->checkBox->isChecked())
    {
        //将文本框数据取出并按行排列
        QFile file(textFile);//文件命名
        if (!file.open(QFile::WriteOnly | QFile::Text))     //检测文件是否打开
        {
            QMessageBox::information(this, "Error Message", "Please Select a Text File!");
            return;
        }
        QTextStream out(&file);                 //分行写入文件
        out << ui->textBrowser->toPlainText();
    }


    // 将文本追加到末尾显示，会导致插入的文本换行
    /*ui->textBrowser->appendPlainText(recBuf);*/

    /*// 在当前位置插入文本，不会发生换行。如果没有移动光标到文件结尾，会导致文件超出当前界面显示范围，界面也不会向下滚动。
    ui->txtRec->insertPlainText(recBuf);
    ui->txtRec->moveCursor(QTextCursor::End);*/

    // 利用一个QString去获取消息框文本，再将新接收到的消息添加到QString尾部，但感觉效率会比当前位置插入低。也不会发生换行
    /*QString txtBuf;
    txtBuf = ui->txtRec->toPlainText();
    txtBuf += recBuf;
    ui->txtRec->setPlainText(txtBuf);
    ui->txtRec->moveCursor(QTextCursor::End);*/

    // 利用一个QString去缓存接收到的所有消息，效率会比上面高一点。但清空接收的时候，要将QString一并清空。
    /*static QString txtBuf;
    txtBuf += recBuf;
    ui->txtRec->setPlainText(txtBuf);
    ui->txtRec->moveCursor(QTextCursor::End);*/
}

/******************************************************************************/
/*判断选择ascii接收还是16进制接收*/
void MainWindow::on_radioButton_clicked()
{
    if(ui->radioButton->isChecked()){
        ui->radioButton_2->setChecked(false);
    }else{
        ui->radioButton_2->setChecked(true);
    }
}
void MainWindow::on_radioButton_2_clicked()
{
    if(ui->radioButton_2->isChecked()){
        ui->radioButton->setChecked(false);
    }else{
        ui->radioButton->setChecked(true);
    }
}

/*判断选择ascii发送还是16进制发送*/
void MainWindow::on_radioButton_5_clicked()
{
    if(ui->radioButton_5->isChecked()){
        ui->radioButton_6->setChecked(false);
    }else{
        ui->radioButton_6->setChecked(true);
    }
}
void MainWindow::on_radioButton_6_clicked()
{
    if(ui->radioButton_6->isChecked()){
        ui->radioButton_5->setChecked(false);
    }else{
        ui->radioButton_5->setChecked(true);
    }
}

/******************************************************************************/
/*选中日志保存文件*/
void MainWindow::on_checkBox_clicked()
{
    if(ui->checkBox->isChecked()){
        textFile = QFileDialog::getSaveFileName(this,tr("Save txt"),"",tr("text (*.txt)")); //选择路径
    }
}
/*是否按日志显示*/
void MainWindow::on_checkBox_3_clicked()
{
    if(ui->checkBox_3->isChecked())
    {
        qDebug() << "log open"<< endl;
    }else {
        qDebug() << "log close"<< endl;
    }
}
/*是否自动换行*/
void MainWindow::on_checkBox_4_clicked()
{
    if(ui->checkBox_4->isChecked())
    {
        qDebug() << "auto change line"<< endl;
    }else {
        qDebug() << "no auto change line"<< endl;
    }
}

// 状态栏标签显示计数值
void MainWindow::setNumOnLabel(QLabel *lbl, QString strS, long num)
{
    // 标签显示
    QString strN;
    strN.sprintf("%ld", num);
    QString str = strS + strN;
    lbl->setText(str);
}


